package util;

import org.springframework.util.Assert;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.HashMap;
import java.util.Map;

/**
 * Java携带HTTP头信息下载网络图片
 * https://blog.csdn.net/meism5/article/details/88415594
 */
public class DownloadImageWithHeaders {

    public static void main(String[] args) {

        // easyPoi文档中图片加载不出来 Excel多Sheet导出 官网例子 http://doc.wupaas.com/docs/easypoi/easypoi-1c0u9bn89hr5u
        // invalid Referer header 403
        // 但是加了Referer依然访问不了 要加这个User-Agent才能下载
        String baiduLogoUrl = "https://static.oschina.net/uploads/space/2017/1128/111045_9s7X_2343396.png"; // 要校验Referer nginx防盗链
        // String baiduLogoUrl = "https://www.oschina.net/uploads/space/2017/1128/111045_9s7X_2343396.png"; // 这个可以直接访问 不校验Referer
        File localFile = new File("D://scenery.jpg");
        Map<String, String> headers = new HashMap();

//         headers.put("Referer", "https://www.oschina.net");
//         headers.put("Referer", "https://www.oschina.net/news/254309/starlite5-linux-tablet");
        // 对 referer 没设置 或 正确的放行
        headers.put("Referer", "https://www.oschina.net");

        // http2.0的请求，作为RFC 描述，Http 请求头不能以冒号开头
        // Java 11 HttpClient 不允许 header 以冒号开头 https://www.coder.work/article/5530255
        // 伪 header 字段由 HttpClient 本身生成。您不需要设置 :method 或 :path header ，HttpClient 会为您完成此操作。
        // headers.put(":authority", "static.oschina.net");
        // headers.put("authority", "static.oschina.net");
        // headers.put("path", "/uploads/space/2017/1128/111045_9s7X_2343396.png");
        // headers.put("Cookie", "_user_behavior_=7f47faa5-3f55-4f70-84e5-31b794b70754; _ga=GA1.1.1611776853.1685676738; Hm_lvt_a411c4d1664dd70048ee98afe7b28f0b=1689754316,1689920442,1692093709,1692147947; _ga_TK89C9ZD80=GS1.1.1692147947.5.0.1692148059.0.0.0");

        // 要加这个
        headers.put("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36");

        Assert.isTrue(downloadImageWithHeaders(baiduLogoUrl, "png", localFile, headers));
    }

    /**
     * 携带头信息下载网络图片
     *
     * @param imageUrl   图片url
     * @param formatName 文件格式名称
     * @param localFile  下载到本地文件
     * @param headers    http协议交互中header信息，如Cookie
     * @return 下载是否成功
     */
    public static boolean downloadImageWithHeaders(String imageUrl, String formatName, File localFile, Map<String, String> headers) {
        boolean isSuccess = false;
        InputStream stream = null;
        try {
            URL url = new URL(imageUrl);
            URLConnection conn = url.openConnection();
            if (headers != null && !headers.isEmpty()) {
                //设置头信息
                for (Map.Entry<String, String> entry : headers.entrySet()) {
                    conn.setRequestProperty(entry.getKey(), entry.getValue());
                }
            }
            conn.setDoInput(true);
            stream = conn.getInputStream();
            BufferedImage bufferedImg = ImageIO.read(stream);
            if (bufferedImg != null) {
                isSuccess = ImageIO.write(bufferedImg, formatName, localFile);
            } else {
                throw new RuntimeException("图片[" + imageUrl + "]下载失败");
            }
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (stream != null) {
                try {
                    stream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return isSuccess;
    }

}
